<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>类型销量统计</title>
<meta name="description"
	content="jquery html5 图表用canvas画布绘制一个动画圆形饼图，分配统计数据量的百分比。html5 canvas,html5下载。" />
<style type="text/css">
* {
	margin: 0;
	padding: 0;
	list-style-type: none;
}

body {
	background: #fff;
	color: #333;
	font-family: "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
	font-size: 0.9em;
}

#container {
	width: 900px;
	margin: 50px auto;
}

#chart, #chartData {
	border: 1px solid #333;
	background: #ebedf2 url("images/gradient.png") repeat-x 0 0;
}

#chart {
	display: block;
	margin: 0 0 50px 0;
	float: left;
	cursor: pointer;
}

#chartData {
	width: 200px;
	margin: 0 40px 0 0;
	float: right;
	border-collapse: collapse;
	box-shadow: 0 0 1em rgba(0, 0, 0, 0.5);
	-moz-box-shadow: 0 0 1em rgba(0, 0, 0, 0.5);
	-webkit-box-shadow: 0 0 1em rgba(0, 0, 0, 0.5);
	background-position: 0 -100px;
}

#chartData th, #chartData td {
	padding: 0.5em;
	border: 1px dotted #666;
	text-align: left;
}

#chartData th {
	border-bottom: 2px solid #333;
	text-transform: uppercase;
}

#chartData td {
	cursor: pointer;
}

#chartData td.highlight {
	background: #e8e8e8;
}

#chartData tr:hover td {
	background: #f0f0f0;
}
</style>
<script type="text/javascript" src="js/jquery-3.1.0.js"></script>
<!--[if IE]>
<script src="http://explorercanvas.googlecode.com/svn/trunk/excanvas.js"></script>
<![endif]-->
<script type="text/javascript">
	// Run the code when the DOM is ready
	$(pieChart);
	function pieChart() {
		// Config settings
		var chartSizePercent = 55; // The chart radius relative to the canvas width/height (in percent)
		var sliceBorderWidth = 1; // Width (in pixels) of the border around each slice
		var sliceBorderStyle = "#fff"; // Colour of the border around each slice
		var sliceGradientColour = "#ddd"; // Colour to use for one end of the chart gradient
		var maxPullOutDistance = 25; // How far, in pixels, to pull slices out when clicked
		var pullOutFrameStep = 4; // How many pixels to move a slice with each animation frame
		var pullOutFrameInterval = 40; // How long (in ms) between each animation frame
		var pullOutLabelPadding = 65; // Padding between pulled-out slice and its label  
		var pullOutLabelFont = "bold 16px 'Trebuchet MS', Verdana, sans-serif"; // Pull-out slice label font
		var pullOutValueFont = "bold 12px 'Trebuchet MS', Verdana, sans-serif"; // Pull-out slice value font
		var pullOutValuePrefix = "$"; // Pull-out slice value prefix
		var pullOutShadowColour = "rgba( 0, 0, 0, .5 )"; // Colour to use for the pull-out slice shadow
		var pullOutShadowOffsetX = 5; // X-offset (in pixels) of the pull-out slice shadow
		var pullOutShadowOffsetY = 5; // Y-offset (in pixels) of the pull-out slice shadow
		var pullOutShadowBlur = 5; // How much to blur the pull-out slice shadow
		var pullOutBorderWidth = 2; // Width (in pixels) of the pull-out slice border
		var pullOutBorderStyle = "#333"; // Colour of the pull-out slice border
		var chartStartAngle = -.5 * Math.PI; // Start the chart at 12 o'clock instead of 3 o'clock
		// Declare some variables for the chart
		var canvas; // The canvas element in the page
		var currentPullOutSlice = -1; // The slice currently pulled out (-1 = no slice)
		var currentPullOutDistance = 0; // How many pixels the pulled-out slice is currently pulled out in the animation
		var animationId = 0; // Tracks the interval ID for the animation created by setInterval()
		var chartData = []; // Chart data (labels, values, and angles)
		var chartColours = []; // Chart colours (pulled from the HTML table)
		var totalValue = 0; // Total of all the values in the chart
		var canvasWidth; // Width of the canvas, in pixels
		var canvasHeight; // Height of the canvas, in pixels
		var centreX; // X-coordinate of centre of the canvas/chart
		var centreY; // Y-coordinate of centre of the canvas/chart
		var chartRadius; // Radius of the pie chart, in pixels
		// Set things up and draw the chart
		init();
		/**
		 * Set up the chart data and colours, as well as the chart and table click handlers,
		 * and draw the initial pie chart
		 */
		function init() {
			// Get the canvas element in the page
			canvas = document.getElementById('chart');
			// Exit if the browser isn't canvas-capable
			if (typeof canvas.getContext === 'undefined')
				return;
			// Initialise some properties of the canvas and chart
			canvasWidth = canvas.width;
			canvasHeight = canvas.height;
			centreX = canvasWidth / 2;
			centreY = canvasHeight / 2;
			chartRadius = Math.min(canvasWidth, canvasHeight) / 2
					* (chartSizePercent / 100);
			// Grab the data from the table,
			// and assign click handlers to the table data cells
			var currentRow = -1;
			var currentCell = 0;
			$('#chartData td')
					.each(
							function() {
								currentCell++;
								if (currentCell % 2 != 0) {
									currentRow++;
									chartData[currentRow] = [];
									chartData[currentRow]['label'] = $(this)
											.text();
								} else {
									var value = parseFloat($(this).text());
									totalValue += value;
									value = value.toFixed(2);
									chartData[currentRow]['value'] = value;
								}
								// Store the slice index in this cell, and attach a click handler to it
								$(this).data('slice', currentRow);
								$(this).click(handleTableClick);
								// Extract and store the cell colour
								if (rgb = $(this).css('color').match(
										/rgb\((\d+), (\d+), (\d+)/)) {
									chartColours[currentRow] = [ rgb[1],
											rgb[2], rgb[3] ];
								} else if (hex = $(this)
										.css('color')
										.match(
												/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/)) {
									chartColours[currentRow] = [
											parseInt(hex[1], 16),
											parseInt(hex[2], 16),
											parseInt(hex[3], 16) ];
								} else {
									alert("Error: Colour could not be determined! Please specify table colours using the format '#xxxxxx'");
									return;
								}
							});
			// Now compute and store the start and end angles of each slice in the chart data
			var currentPos = 0; // The current position of the slice in the pie (from 0 to 1)
			for ( var slice in chartData) {
				chartData[slice]['startAngle'] = 2 * Math.PI * currentPos;
				chartData[slice]['endAngle'] = 2
						* Math.PI
						* (currentPos + (chartData[slice]['value'] / totalValue));
				currentPos += chartData[slice]['value'] / totalValue;
			}
			// All ready! Now draw the pie chart, and add the click handler to it
			drawChart();
			$('#chart').click(handleChartClick);
		}
		/**
		 * Process mouse clicks in the chart area.
		 * If a slice was clicked, toggle it in or out.
		 * If the user clicked outside the pie, push any slices back in.
		 * @param Event The click event
		 */
		function handleChartClick(clickEvent) {
			// Get the mouse cursor position at the time of the click, relative to the canvas
			var mouseX = clickEvent.pageX - this.offsetLeft;
			var mouseY = clickEvent.pageY - this.offsetTop;
			// Was the click inside the pie chart?
			var xFromCentre = mouseX - centreX;
			var yFromCentre = mouseY - centreY;
			var distanceFromCentre = Math.sqrt(Math.pow(Math.abs(xFromCentre),
					2)
					+ Math.pow(Math.abs(yFromCentre), 2));
			if (distanceFromCentre <= chartRadius) {
				// Yes, the click was inside the chart.
				// Find the slice that was clicked by comparing angles relative to the chart centre.
				var clickAngle = Math.atan2(yFromCentre, xFromCentre)
						- chartStartAngle;
				if (clickAngle < 0)
					clickAngle = 2 * Math.PI + clickAngle;
				for ( var slice in chartData) {
					if (clickAngle >= chartData[slice]['startAngle']
							&& clickAngle <= chartData[slice]['endAngle']) {
						// Slice found. Pull it out or push it in, as required.
						toggleSlice(slice);
						return;
					}
				}
			}
			// User must have clicked outside the pie. Push any pulled-out slice back in.
			pushIn();
		}
		/**
		 * Process mouse clicks in the table area.
		 * Retrieve the slice number from the jQuery data stored in the
		 * clicked table cell, then toggle the slice
		 * @param Event The click event
		 */
		function handleTableClick(clickEvent) {
			var slice = $(this).data('slice');
			toggleSlice(slice);
		}
		/**
		 * Push a slice in or out.
		 * If it's already pulled out, push it in. Otherwise, pull it out.
		 * @param Number The slice index (between 0 and the number of slices - 1)
		 */
		function toggleSlice(slice) {
			if (slice == currentPullOutSlice) {
				pushIn();
			} else {
				startPullOut(slice);
			}
		}
		/**
		 * Start pulling a slice out from the pie.
		 * @param Number The slice index (between 0 and the number of slices - 1)
		 */
		function startPullOut(slice) {
			// Exit if we're already pulling out this slice
			if (currentPullOutSlice == slice)
				return;
			// Record the slice that we're pulling out, clear any previous animation, then start the animation
			currentPullOutSlice = slice;
			currentPullOutDistance = 0;
			clearInterval(animationId);
			animationId = setInterval(function() {
				animatePullOut(slice);
			}, pullOutFrameInterval);
			// Highlight the corresponding row in the key table
			$('#chartData td').removeClass('highlight');
			var labelCell = $('#chartData td:eq(' + (slice * 2) + ')');
			var valueCell = $('#chartData td:eq(' + (slice * 2 + 1) + ')');
			labelCell.addClass('highlight');
			valueCell.addClass('highlight');
		}
		/**
		 * Draw a frame of the pull-out animation.
		 * @param Number The index of the slice being pulled out
		 */
		function animatePullOut(slice) {
			// Pull the slice out some more
			currentPullOutDistance += pullOutFrameStep;
			// If we've pulled it right out, stop animating
			if (currentPullOutDistance >= maxPullOutDistance) {
				clearInterval(animationId);
				return;
			}
			// Draw the frame
			drawChart();
		}
		/**
		 * Push any pulled-out slice back in.
		 * Resets the animation variables and redraws the chart.
		 * Also un-highlights all rows in the table.
		 */
		function pushIn() {
			currentPullOutSlice = -1;
			currentPullOutDistance = 0;
			clearInterval(animationId);
			drawChart();
			$('#chartData td').removeClass('highlight');
		}
		/**
		 * Draw the chart.
		 * Loop through each slice of the pie, and draw it.
		 */
		function drawChart() {
			// Get a drawing context
			var context = canvas.getContext('2d');
			// Clear the canvas, ready for the new frame
			context.clearRect(0, 0, canvasWidth, canvasHeight);
			// Draw each slice of the chart, skipping the pull-out slice (if any)
			for ( var slice in chartData) {
				if (slice != currentPullOutSlice)
					drawSlice(context, slice);
			}
			// If there's a pull-out slice in effect, draw it.
			// (We draw the pull-out slice last so its drop shadow doesn't get painted over.)
			if (currentPullOutSlice != -1)
				drawSlice(context, currentPullOutSlice);
		}
		/**
		 * Draw an individual slice in the chart.
		 * @param Context A canvas context to draw on  
		 * @param Number The index of the slice to draw
		 */
		function drawSlice(context, slice) {
			// Compute the adjusted start and end angles for the slice
			var startAngle = chartData[slice]['startAngle'] + chartStartAngle;
			var endAngle = chartData[slice]['endAngle'] + chartStartAngle;
			if (slice == currentPullOutSlice) {
				// We're pulling (or have pulled) this slice out.
				// Offset it from the pie centre, draw the text label,
				// and add a drop shadow.
				var midAngle = (startAngle + endAngle) / 2;
				var actualPullOutDistance = currentPullOutDistance
						* easeOut(currentPullOutDistance / maxPullOutDistance,
								.8);
				startX = centreX + Math.cos(midAngle) * actualPullOutDistance;
				startY = centreY + Math.sin(midAngle) * actualPullOutDistance;
				context.fillStyle = 'rgb(' + chartColours[slice].join(',')
						+ ')';
				context.textAlign = "center";
				context.font = pullOutLabelFont;
				context
						.fillText(
								chartData[slice]['label'],
								centreX
										+ Math.cos(midAngle)
										* (chartRadius + maxPullOutDistance + pullOutLabelPadding),
								centreY
										+ Math.sin(midAngle)
										* (chartRadius + maxPullOutDistance + pullOutLabelPadding));
				context.font = pullOutValueFont;
				context
						.fillText(
								pullOutValuePrefix
										+ chartData[slice]['value']
										+ " ("
										+ (parseInt(chartData[slice]['value']
												/ totalValue * 100 + .5))
										+ "%)",
								centreX
										+ Math.cos(midAngle)
										* (chartRadius + maxPullOutDistance + pullOutLabelPadding),
								centreY
										+ Math.sin(midAngle)
										* (chartRadius + maxPullOutDistance + pullOutLabelPadding)
										+ 20);
				context.shadowOffsetX = pullOutShadowOffsetX;
				context.shadowOffsetY = pullOutShadowOffsetY;
				context.shadowBlur = pullOutShadowBlur;
			} else {
				// This slice isn't pulled out, so draw it from the pie centre
				startX = centreX;
				startY = centreY;
			}
			// Set up the gradient fill for the slice
			var sliceGradient = context.createLinearGradient(0, 0,
					canvasWidth * .75, canvasHeight * .75);
			sliceGradient.addColorStop(0, sliceGradientColour);
			sliceGradient.addColorStop(1, 'rgb('
					+ chartColours[slice].join(',') + ')');
			// Draw the slice
			context.beginPath();
			context.moveTo(startX, startY);
			context.arc(startX, startY, chartRadius, startAngle, endAngle,
					false);
			context.lineTo(startX, startY);
			context.closePath();
			context.fillStyle = sliceGradient;
			context.shadowColor = (slice == currentPullOutSlice) ? pullOutShadowColour
					: "rgba( 0, 0, 0, 0 )";
			context.fill();
			context.shadowColor = "rgba( 0, 0, 0, 0 )";
			// Style the slice border appropriately
			if (slice == currentPullOutSlice) {
				context.lineWidth = pullOutBorderWidth;
				context.strokeStyle = pullOutBorderStyle;
			} else {
				context.lineWidth = sliceBorderWidth;
				context.strokeStyle = sliceBorderStyle;
			}
			// Draw the slice border
			context.stroke();
		}
		/**
		 * Easing function.
		 * A bit hacky but it seems to work! (Note to self: Re-read my school maths books sometime)
		 * @param Number The ratio of the current distance travelled to the maximum distance
		 * @param Number The power (higher numbers = more gradual easing)
		 * @return Number The new ratio
		 */
		function easeOut(ratio, power) {
			return (Math.pow(1 - ratio, power) + 1);
		}
	};
</script>
</head>
<body>
	
	<h1>电脑类型销量统计图</h1>

	<div id="container">
		<canvas id="chart" width="530" height="440"></canvas>
		<table id="chartData">
			<tr>
				<th>电脑类型</th>
				<th>销售量</th>
			</tr>
			<tr style="color: #0DA068">
				<td>商务笔记本</td>
				<td>6702</td>
			</tr>
			<tr style="color: #194E9C">
				<td>游戏笔记本</td>
				<td>13160</td>
			</tr>
			<tr style="color: #ED9C13">
				<td>台式机</td>
				<td>10200</td>
			</tr>
			<tr style="color: #ED5713">
				<td>办公笔记本</td>
				<td>9099</td>
			</tr>
			<tr style="color: #057249">
				<td>一体机</td>
				<td>2025</td>
			</tr>
			<tr style="color: #5F91DC">
				<td>平板电脑</td>
				<td>9836</td>
			</tr>
			<tr style="color: #F88E5D">
				<td>超薄本</td>
				<td>5632</td>
			</tr>
		</table>
	</div>
	<!--container end-->
</body>
</html>